#include "ParametersManager.cuh"
#include <unistd.h>
#include <stdio.h>

ParametersManager::ParametersManager(int argc, char** argv)
{
	correct = false;
	has_help = false;
	input_file = NULL;
	output_file = NULL;
	number_of_threads = 1;
	number_of_blocks = 1;
	unknown_parameter = '\0';
	verbosity_level = 0;
	strategy = DISTRIBUTE_JOBS_PER_THREAD;
	sequential_as_parallel = false;
	preprocess_unary_clauses = true;
	process(argc, argv);
}

void ParametersManager::process(int argc, char** argv)
{
	bool has_input_file = false;

	if(argc <= 1)
	{
		correct = false;
		return;
	}

	if(argv[1][0] != '-')
	{
		has_input_file = true;
		input_file = argv[1];
	}

	int c;

	while((c = getopt(argc, argv, "ho:t:b:v:s:pu:")) != -1)
	{
		switch(c)
		{
			case 'h' :
				has_help = true;
				break;
			case 'o' :
				output_file = optarg;
				break;
			case 't' :
				number_of_threads = atoi(optarg);
				break;
			case 'b' :
				number_of_blocks = atoi(optarg);
				break;
			case 'v' :
				verbosity_level = atoi(optarg);
				break;
			case 's' :
				if(strcmp("j", optarg) == 0)
				{
					strategy = DISTRIBUTE_JOBS_PER_THREAD;
				}
				else
				{
					if(strcmp("u", optarg) == 0)
					{
						strategy = UNIFORM;
					}
					else
					{
						printf("Parameter %s for -s is not recognized\n", optarg);
						correct = false;
						return;
					}
				}
				break;

			case 'p' :
				sequential_as_parallel = true;
				break;
			case 'u' :
				if(strcmp(optarg, "ON") == 0)
				{
					preprocess_unary_clauses = true;
				}
				else
				{
					if(strcmp(optarg, "OFF") == 0)
					{
						preprocess_unary_clauses = false;
					}
					else
					{
						correct = false;
						printf("Parameter 'u' requires either 'ON' or 'OFF' as arguments. "
								"'%s' is unrecognized.\n",
								optarg);
					}
				}
				break;

			case '?' :
				unknown_parameter = (char) optopt;
				correct = false;
				return;
		}
	}

	if(has_input_file || has_help)
	{
		correct = true;
	}
	else
	{
		correct = false;
		printf("Expected input or help parameter.\n");
	}

#if CONFLICT_ANALYSIS_STRATEGY == TWO_WATCHED_LITERALS

	if(!preprocess_unary_clauses)
	{
		printf("Warning: preprocessing unary clauses is OFF, but it is required for "
				"two-watched literals strategy. Turning it ON now...\n");
		preprocess_unary_clauses = true;
	}

#endif

	return;

}

bool ParametersManager::valid_parameters()
{
	return correct;
}

char* ParametersManager::get_input_file()
{
	return input_file;
}

char* ParametersManager::get_output_file()
{
	return output_file;
}

int ParametersManager::get_number_of_threads()
{
	return number_of_threads;
}

int ParametersManager::get_number_of_blocks()
{
	return number_of_blocks;
}

bool ParametersManager::has_help_parameter()
{
	return has_help;
}

char ParametersManager::get_unknown_parameter()
{
	return unknown_parameter;
}

int ParametersManager::get_verbosity_level()
{
	return verbosity_level;
}

ChoosingStrategy ParametersManager::get_choosing_strategy()
{
	return strategy;
}

bool ParametersManager::get_sequential_as_parallel()
{
	return sequential_as_parallel;
}
bool ParametersManager::get_preprocess_unary_clauses()
{
	return preprocess_unary_clauses;
}

void ParametersManager::force_sequential_configuration()
{
	number_of_blocks = 1;
	number_of_threads = 1;
	sequential_as_parallel = false;
}

void ParametersManager::print_help(char** argv)
{
	char* pch = strtok (argv[0],"/");
	char* last = pch;
	while ((pch= strtok (NULL, "/")) != NULL)
	{
		last = pch;
	}

	printf("Usage: %s <cnf> [OPTIONS]\nOPTIONS:\n"
			"-h: help\n-o <file>: output file\n"
			"-t <number>: Number of threads\n"
			"-b <number>: Number of blocks\n"
			"-p: When used with '-t 1 -b 1', forces the execution of the parallel strategy, with jobs creation, but running with 1 thread and 1 block.\n"
			"-s <strategy>: Strategy for generating the jobs. Options:\n"
			"\tj: A defined number of jobs per thread (all threads, in all blocks) is created\n"
			"\tu: Always the same number of jobs is created, regardless of number of threads\n"
			"-u <ON|OFF> : turns ON\OFF the pre-processing of unary clauses\n\n"
			"The parameter '-h' may be used without the input CNF parameter\n", last);
}
